package com.smart.wap.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import com.smart.manager.member.entities.enums.*;
import com.smart.manager.member.entities.models.*;
import com.smart.manager.member.entities.models.query.*;
import com.smart.manager.member.entities.views.MemberPigView;
import com.smart.manager.member.entities.views.MemberView;
import com.smart.manager.member.entities.views.query.QMemberView;
import com.smart.manager.member.repository.*;
import com.smart.manager.pop.entities.assembler.IncludeData;
import com.smart.manager.pop.entities.enums.CDKState;
import com.smart.manager.pop.entities.models.PopBasicDiamond;
import com.smart.manager.pop.entities.models.PopDisExchange;
import com.smart.manager.pop.entities.models.query.QPopBasicDiamond;
import com.smart.manager.pop.entities.models.query.QPopDisExchange;
import com.smart.manager.product.entities.enums.PigstyKind;
import com.smart.manager.product.entities.models.PigGoods;
import com.smart.manager.product.entities.models.query.QPigGoods;
import com.smart.manager.product.entities.views.PropsComboView;
import com.smart.manager.product.entities.views.PropsServeView;
import com.smart.manager.product.entities.views.PropsSnacksView;
import com.smart.manager.product.entities.views.query.QPropsServeView;
import com.smart.manager.product.entities.views.query.QPropsSnacksView;
import com.smart.manager.work.entities.assembler.WorkOrder;
import com.smart.manager.work.entities.enums.PigOrderKind;
import com.smart.manager.work.entities.enums.PigOrderStatus;
import com.smart.manager.work.entities.models.PigOrder;
import com.smart.manager.work.entities.models.PigOrderFoods;
import com.smart.manager.work.entities.models.query.QPigOrder;
import com.smart.manager.work.entities.models.query.QPigOrderFoods;
import com.smart.manager.work.repository.PigOrderRepository;
import com.smart.service.remind.RemindService;
import com.smart.utils.MemberAcl;
import com.smart.wap.bodys.PigBody;
import com.smart.wap.bodys.ShopResult;
import com.smart.wap.responsive.PigResponsive;
import io.ebean.annotation.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 猪仔操作
 *
 * @author leo
 * @date 2023/09/21
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PigService {

    private final MemberAccountRepository memberAccountRepository;
    private final MemberMaterialPigUseRepository memberMaterialPigUseRepository;
    private final MemberMaterialPropsRepository memberMaterialPropsRepository;
    private final MemberMaterialPigPlanRepository memberMaterialPigPlanRepository;
    private final PigOrderRepository pigOrderRepository;
    private final MemberMaterialPigRepository materialPigRepository;
    private final RemindService remindService;


    /**
     * 使用零食
     *
     * @param memberId 玩家id
     * @param body     body
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> feeding(Long memberId, PigBody.EditBody body) {
        MemberProfileAccount account = memberAccountRepository.getAccount(memberId);

        //查找物品
        Optional<MemberMaterialProps> oneOrEmpty = new QMemberMaterialProps().member.id.eq(account.getMember().getId()).code.eq(body.getSnackCode()).setMaxRows(1).findOneOrEmpty();
        Assert.isFalse(oneOrEmpty.isEmpty(), "背包没有该物品!");
        MemberMaterialProps props = oneOrEmpty.get();
        switch (props.getKind()) {
            case L1:
                //使用零食忽略
                break;
            case L2:
                //改名 -- 忽略
                break;
            case L3:
                //使用道具服务 -- 忽略
                break;
            case L4:
                //TODO: 给猪仔使用套餐
                log.warn("给猪仔使用套餐");
                return null;
                //使用套餐
            case L5:
                //使用立减
                log.warn("使用立减忽略");
                return null;
            case L6:
                //使用能量
                exchangeEnergy(memberId,props.getCode());
                deduct(props,body.getNumber());
                return Map.of("code", body.getSnackCode(), "number", body.getNumber());
            case L7:
                //使用金币
                exchangeGold(memberId,props.getCode());
                deduct(props,body.getNumber());
                return Map.of("code", body.getSnackCode(), "number", body.getNumber());
        }


        //查找猪仔
        Optional<MemberMaterialPig> empty = new QMemberMaterialPig().code.eq(body.getPigCode()).setMaxRows(1).findOneOrEmpty();
        Assert.isFalse(empty.isEmpty(), "操作的猪猪不存在!");

        if (ObjUtil.isNotNull(empty.get().getCloseMember())) {
            Assert.isTrue(empty.get().getCloseMember().getId().equals(memberId) || empty.get().getMember().getId().equals(memberId), "您不能操作别人的猪猪");
        } else {
            Assert.isTrue(empty.get().getMember().getId().equals(memberId), "您不能操作别人的猪猪");
        }

        MemberMaterialPig memberMaterialPig = empty.get();
        if (ObjUtil.isNotNull(memberMaterialPig.getCloseMember())) {
            Assert.isTrue(memberMaterialPig.getCloseMember().equals(account.getMember()) || memberMaterialPig.getMember().equals(account.getMember()), "您不能操作别人的猪猪!");
        }
        //扣减背包
        deduct(props,body.getNumber());


        memberMaterialPigUseRepository.add(account.getMember().getId(), memberMaterialPig.getId(), PigUseKind.L3, PigUseState.DSX, body.getNumber(), "");
        if (props.getKind().equals(PropsKind.L1)) {
            Optional<PropsSnacksView> orEmpty = new QPropsSnacksView().code.eq(body.getSnackCode()).findOneOrEmpty();
            Assert.isFalse(orEmpty.isEmpty(), "使用的物品不存在或者已下架!");
            //创建零食排队列表
            Optional<MemberMaterialSort> sortOptional = new QMemberMaterialSort().pigId.id.eq(memberMaterialPig.getId()).snacks.code.eq(body.getSnackCode()).status.eq(SortState.DSX).setMaxRows(1).findOneOrEmpty();
            //叠加
            if (sortOptional.isEmpty()) {
                new MemberMaterialSort().setSnacks(orEmpty.get()).setPigId(new MemberPigView()
                        .setId(memberMaterialPig.getId())).setStatus(SortState.DSX).setWorkOrder(null).setNumber(body.getNumber()).insert();
            } else {
                MemberMaterialSort sort = sortOptional.get();
                sort.setNumber(sort.getNumber() + body.getNumber()).update();
            }
            return Map.of("code", body.getSnackCode(), "number", body.getNumber());
        }
        Optional<PropsServeView> orEmpty = new QPropsServeView().code.eq(body.getSnackCode()).findOneOrEmpty();
        Assert.isFalse(orEmpty.isEmpty(), "使用的物品不存在或者已下架!");

        //创建服务工单
        WorkOrder.ServiceTicketBody ticket = new WorkOrder.ServiceTicketBody().setCombo(orEmpty.get());
        //生成服务工单
        String order = pigOrderRepository.createAWorkOrder(new MemberPigView().setId(memberMaterialPig.getId()), memberMaterialPig.getStaff(), PigOrderKind.L5, PigOrderStatus.PROGRESS, ticket);
        //添加 猪仔消费记录
        memberMaterialPigUseRepository.add(account.getMember().getId(), memberMaterialPig.getId(), PigUseKind.L2, PigUseState.DSX, 1, order);

        return Map.of("code", body.getSnackCode(), "number", body.getNumber());
    }


    public void deduct(MemberMaterialProps props,Integer number) {
        List<PropsKind> kinds = List.of(PropsKind.L3, PropsKind.L2);
        if (kinds.contains(props.getKind())) {
            Assert.isFalse(number > 1, "道具不能批量使用!");
        }
        Assert.isTrue(props.getNumber() >= number, "背包物品不足!");
        int quantity = props.getNumber() - number;
        if (quantity <= 0) {
            props.delete();
        } else {
            props.setNumber(quantity).update();
        }
    }


    /**
     * 兑换金币
     * @param id
     */
    public void exchangeGold(Long id,String code){

        Optional<PopBasicDiamond> diamond = new QPopBasicDiamond().code.eq(code).setMaxRows(1).findOneOrEmpty();
        diamond.ifPresent(x->{
            memberAccountRepository.saveEvent(id, CoinAccountEvent.DIAMOND, x.getQuantity(), "钻石兑换");
        });

    }
    /**
     * 兑换能量
     * @param id
     */
    public void exchangeEnergy(Long id,String code){
        Optional<PopBasicDiamond> diamond = new QPopBasicDiamond().code.eq(code).setMaxRows(1).findOneOrEmpty();
        diamond.ifPresent(x->{
            memberAccountRepository.savePowerEvent(id, EnergyAccountEvent.DIAMOND, x.getQuantity(), "钻石兑换");
        });

    }


    /**
     * 查询 背包/零食
     *
     * @param id 会员id
     * @return {@link String}
     */
    public List<MemberMaterialProps> getPropsList(Long id) {
        return memberMaterialPropsRepository.getMemberList(id);
    }

    /**
     * 获取用户的所有猪仔
     *
     * @param id 会员id
     * @return {@link List}<{@link MemberMaterialPig}>
     */
    public List<MemberMaterialPig> getPigOneList(Long id, Boolean combine) {
        return memberMaterialPigPlanRepository.getOneList(id, combine);
    }


    /**
     * 排行榜 2小时缓存更新
     *
     * @return {@link List}<{@link MemberMaterialPig}>
     */
    public List<PigBody.ReturnBody> getPigRanking() {
//        List<PigBody.ReturnBody> ranking = cacheService.getRankingCache().get("ranking");
//        if (ObjUtil.isEmpty(ranking)){
        QMemberMaterialPig query = new QMemberMaterialPig().pigLevel.isNotNull().order().pigLevel.day.desc().setMaxRows(10);
        List<MemberMaterialPig> pigs = query.findList();
        return BeanUtil.copyToList(pigs, PigBody.ReturnBody.class);
//            cacheService.getRankingCache().put("ranking",ranking);
//        }
//        return ranking;
    }
    /**
     * 修改猪仔名称
     *
     * @param id 会员id
     * @return {@link List}<{@link MemberMaterialPig}>
     */
    public Map<String, String> addPigName(Long id, PigBody.NameBody body) {
        Optional<MemberMaterialPig> orEmpty = new QMemberMaterialPig().member.id.eq(id).code.eq(body.getPigCode()).findOneOrEmpty();
        Assert.isFalse(orEmpty.isEmpty(), "没有找到您的猪仔!");
        MemberMaterialPig materialPig = orEmpty.get();
        materialPig.setName(body.getName()).update();
        log.warn("猪仔数据 =  {}", materialPig);
        if (ObjUtil.isNull(materialPig.getPigLevel()) || materialPig.getPigLevel().getKind().equals(PigstyKind.COMMON)) {
            // 为空等于  或者等于散养
            // 散养 不处理
            log.warn("散养不处理 == {}", materialPig);
            return Map.of("code", orEmpty.get().getCode(), "name", body.getName());
        }
        log.warn("非散养处理 == {}", materialPig);
        //判断有没有改名卡
        MemberMaterialProps props = getKnapsack(body.getPigCode());
        Assert.isTrue(props.getNumber() >= 1, "背包物品不足!");
        int quantity = props.getNumber() - 1;
        if (quantity <= 0) {
            props.delete();
        } else {
            props.setNumber(quantity).update();
        }

//        if (ObjUtil.isNotNull(materialPig.getPigsty())) {
//            List<String> cameraCode = materialPig.getPigsty().getCameraCode();
//            List<BasicCameraDetail> list = new QBasicCameraDetail().passageId.in(cameraCode).findList();
//            for (BasicCameraDetail detail : list) {
//                String builder = "猪猪名称:" + body.getName() + "\n" +
//                        "会员ID:" + materialPig.getMember().getNickName() + "\n" +
//                        "猪圈ID:" + materialPig.getPigsty().getCode();
//                basicCameraDetailRepository.updateOsdName(detail, builder);
//            }
//        }
        return Map.of("code", orEmpty.get().getCode(), "name", body.getName());
    }

    /**
     * 获取猪仔喂食记录
     *
     * @param code 猪仔code
     * @return {@link List}<{@link PigResponsive}>
     */
    public List<PigResponsive.Feeding> getFeed(String code) {
        MemberMaterialPig pig = getMemberMaterialPig(code);
        List<PigOrderFoods> orders = new QPigOrderFoods().pigCodeList.contains(pig.getCode()).kind.eq(PigOrderKind.L3).order().createTime.desc().findList();
        return orders.stream().filter(ObjUtil::isNotNull).map(c -> new PigResponsive.Feeding()
                        .setVideo(c.getVideo())
                        .setStaff(c.getStaff())
                        .setCompleteTime(c.getCompleteTime())
                        .setCreateTime(c.getCreateTime())
                        .setStatus(c.getStatus())
                        .setCode(c.getCode()).setContent(BeanUtil.copyProperties(c.getContent(), WorkOrder.FeedBody.class)))
                .collect(Collectors.toList());
    }

    /**
     * 获取猪仔治疗记录
     *
     * @param code 猪仔code
     * @return {@link List}<{@link PigResponsive}>
     */
    public List<PigResponsive.Treat> getTreatment(String code) {
        MemberMaterialPig pig = getMemberMaterialPig(code);
        List<PigOrder> orders = new QPigOrder().pig.id.eq(pig.getId()).kind.eq(PigOrderKind.L4).order().createTime.desc().findList();
        return orders.stream().filter(ObjUtil::isNotNull).map(c -> new PigResponsive.Treat()
                        .setStaff(c.getStaff())
                        .setCompleteTime(c.getCompleteTime())
                        .setCreateTime(c.getCreateTime())
                        .setStatus(c.getStatus())
                        .setCode(c.getCode())
                        .setContent((String) c.getContent()))
                .collect(Collectors.toList());
    }


    /**
     * 获取服务
     *
     * @param code
     * @return {@link List}<{@link PigResponsive.Serve}>
     */
    public List<PigResponsive.Serve> getServe(String code) {
        MemberMaterialPig pig = getMemberMaterialPig(code);
        List<PigOrder> orders = new QPigOrder().pig.id.eq(pig.getId()).kind.eq(PigOrderKind.L5).order().createTime.desc().findList();
        return orders.stream().filter(ObjUtil::isNotNull).map(c -> new PigResponsive.Serve()
                        .setStaff(c.getStaff())
                        .setCompleteTime(c.getCompleteTime())
                        .setStatus(c.getStatus())
                        .setVideo(c.getVideo())
                        .setCreateTime(c.getCreateTime())
                        .setCode(c.getCode()).setCombo(BeanUtil.copyProperties(c.getContent(), WorkOrder.ServiceTicketBody.class).getCombo()))
                .collect(Collectors.toList());
    }

    public PigResponsive.Combo getEatCombo(String code) {
        MemberMaterialPig pig = getMemberMaterialPig(code);
        List<MemberMaterialPigPlan> plans = new QMemberMaterialPigPlan().pigId.id.eq(pig.getId()).status.eq(PigPlanStatus.L2).order().eatDate.desc().findList();
        if (plans.isEmpty()) {
            log.warn("没有计划");
            //没有计划
            return null;
        }
        List<PropsComboView> collect = plans.stream().filter(ObjUtil::isNotNull).map(MemberMaterialPigPlan::getCombo).collect(Collectors.toList());
        Set<LocalDate> times = plans.stream().filter(ObjUtil::isNotNull).map(MemberMaterialPigPlan::getEatDate).collect(Collectors.toSet());
        log.warn(code + "  " + times);
        return new PigResponsive.Combo().setComboNumber(collect.size()).setComboList(collect).setDay(times.size());
    }


    public List<PigResponsive.StepWarm> getMotion(String code) {
        MemberMaterialPig pig = getMemberMaterialPig(code);
        List<MemberMaterialPigState> states = new QMemberMaterialPigState().pigId.eq(pig.getId()).order().timing.desc().findList();
        return states.stream().filter(ObjUtil::isNotNull).map(x -> new PigResponsive.StepWarm()
                        .setDate(x.getTiming())
                        .setWarm(x.getTemp())
                        .setStep(x.getStep()))
                .collect(Collectors.toList());
    }


    public MemberMaterialPig getMemberMaterialPig(String code) {
        Optional<MemberMaterialPig> pig = new QMemberMaterialPig().code.eq(code).findOneOrEmpty();
        Assert.isFalse(pig.isEmpty(), "查询的猪仔不存在!");
        return pig.get();
    }


    /**
     * 获取农管家的工单数据
     *
     * @param code
     * @return {@link List}<{@link PigOrder}>
     */
    public List<PigOrder> getWorkOrder(String code) {
        MemberMaterialPig one = new QMemberMaterialPig().code.eq(code).setMaxRows(1).findOne();
        Assert.isFalse(ObjUtil.isNull(one), "未找到猪仔!");
        Assert.isFalse(ObjUtil.isNull(one.getStaff()), "当前猪仔还未绑定农管家请稍后再试");
        LocalDateTime start = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        LocalDateTime stop = LocalDateTime.now();
        return new QPigOrder().staff.eq(one.getStaff()).createTime.between(start, stop).pig.id.eq(one.getId()).order().completeTime.desc().findList();
    }


    /**
     * 获取背包数据
     */
    public MemberMaterialProps getKnapsack(String SnackCode) {
        MemberMaterialProps props = new QMemberMaterialProps().member.id.eq(MemberAcl.getLoginId()).kind.eq(PropsKind.L2).setMaxRows(1).findOne();
        Assert.isFalse(ObjUtil.isEmpty(props), "背包没有该物品!");
        return props;
    }


    public ShopResult.Rem useCdk(String cdk) {
        return isExchange(cdk, MemberAcl.getLoginId(), true);
    }


    public ShopResult.Rem isExchange(String cdk, Long id, Boolean isUse) {
        PopDisExchange exchange = new QPopDisExchange().redeemCodes.eq(cdk).setMaxRows(1).findOne();
        Assert.isFalse(ObjUtil.isNull(exchange), "兑换码不正确!");
        Assert.isFalse(exchange.getState().equals(CDKState.ALREADY), "兑换码已被使用!");
        ShopResult.Rem rem = new ShopResult.Rem();
        MemberView view = new QMemberView().id.eq(id).setMaxRows(1).findOne();
        log.warn("兑换人 {}  兑换信息 {}",view,exchange);
        switch (exchange.getKind()) {
            case GOLD:
                rem.setTitle(exchange.getKind().getLabel() + "卷 将会获得" + exchange.getProportion().intValue() + "金币").setAmount(exchange.getProportion().intValue()).setKind(exchange.getKind());
                if (isUse) {
                    memberAccountRepository.saveEvent(id, CoinAccountEvent.CDKDS, exchange.getProportion().intValue(), "CDK兑换: " + cdk);
                    exchange.setState(CDKState.ALREADY).setUseMember(view).setUseTime(LocalDateTime.now()).update();
                }
                return rem;
            case ENERGY:
                rem.setTitle(exchange.getKind().getLabel() + "卷 将会获得" + exchange.getProportion().intValue() + "能量").setAmount(exchange.getProportion().intValue()).setKind(exchange.getKind());
                if (isUse) {
                    memberAccountRepository.savePowerEvent(id, EnergyAccountEvent.CDKDH, exchange.getProportion().intValue(), "CDK兑换: " + cdk);
                    exchange.setState(CDKState.ALREADY).setUseMember(view).setUseTime(LocalDateTime.now()).update();
                }
                return rem;
            case PIG:
                //生成一只价格最低的猪给兑换人
                IncludeData includeData = BeanUtil.copyProperties(exchange.getIncludeContent(), IncludeData.class);
                log.warn("includeData = {}",includeData);
                PigGoods goods = new QPigGoods().code.eq(includeData.getPigGoodsCode()).findOne();
                rem.setTitle(exchange.getKind().getLabel() + "卷").setAmount(0).setKind(exchange.getKind()).setCode(goods.getCode());
                if (isUse) {
                    MemberMaterialPig pig = materialPigRepository.addPig(goods, false, view,includeData.getMonths());
                    remindService.sendExchangeSuccessfulMsg(view.getId(),pig);
                    exchange.setState(CDKState.ALREADY).setUseMember(view).setUseTime(LocalDateTime.now()).update();
                }
                return rem;
            default:
                Assert.isTrue(false, "当前类型兑换卷暂不支持使用!");
                return null;
        }
    }



    public void exchangePig(PopDisExchange cdk){



    }

}
